home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir35
/
cff51b.zip
/
PORTS
/
CFPORT.DJC
< prev
next >
Wrap
Text File
|
1993-10-23
|
14KB
|
657 lines
/* CFPORT.C */
/* PORTABILITY FOR CFF -- MODIFY TO SUIT THE COMPILER/OS IN USE */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <direct.h>
#include <errno.h>
#include <io.h>
#include <stdio.h>
#include <time.h>
#include <dirent.h>
#include "../cff.h"
extern void *mymemmove(void *, void *, long);
#define PCDOS 1
#define NIBBLE 128
#define CHUNK_SIZE 8192
#ifndef HEAPSTART
#define HEAPSTART 0x500000
#endif
unsigned long heapcreep;
void *heapstart = (void *)HEAPSTART;
extern volatile int errno;
static STOR BIGZERO;
/* DUMMY ROUTINES TO PREVENT LINKING UNWANTED MALLOC LIKE STUFF */
int _heapchk(void)
{
return 0;
}
int _heapset(unsigned a)
{
return 0;
}
void *_expand (void *mem, size_t new_size)
{
return NULL;
}
size_t _msize (const void *mem)
{
return mallocsize(mem);
}
unsigned malloc_usable_size (void *mem)
{
return mallocsize((const void *)mem);
}
/* ---------------- END OF MALLOC DUMMYS ------------- */
static __inline__ unsigned long
round_up(long size, long amt)
{
return (size&(amt-1)) ? size+(amt-(size&(amt-1))) : size;
}
static int testflags = 0;
void
cfport_settestflags(int flags)
{
testflags |= flags;
}
void
cfport_clrtestflags(int flags)
{
testflags &= ~flags;
}
static void
fix_statbuf(struct stat *stat, CFSTAT *sbuf)
{
sbuf->st_atime = stat->st_atime;
sbuf->st_mtime = stat->st_mtime;
sbuf->st_ctime = stat->st_ctime;
sbuf->st_size = stat->st_size;
sbuf->st_alloc = stat->st_size;
sbuf->st_filesize = stat->st_size;
sbuf->st_filealloc = stat->st_size;
sbuf->st_blksize = stat->st_blksize;
sbuf->st_dev = stat->st_dev;
sbuf->st_ino = stat->st_ino;
sbuf->st_nlink = stat->st_nlink;
sbuf->st_uid = stat->st_uid;
sbuf->st_gid = stat->st_gid;
sbuf->st_rdev = stat->st_rdev;
sbuf->st_mode = stat->st_mode;
}
void *
PORTSBRK(unsigned long amt)
{
return ((void *)sbrk(amt));
}
void
PORTHEAPSTART(void)
{
void *curstart = sbrk(0);
char *newstart = NULL;
if(curstart > heapstart)
{
cfprintf("CFFINIT: The heap safety zone was exceeded by %d bytes.\n",
-((long)(heapstart - curstart)));
exit(-1);
}
heapcreep = (unsigned long)(heapstart - curstart);
if((newstart = (void *)sbrk(heapcreep)) == (void *)-1) {
cfprintf("Failed to set heap: zone=%lu HEAPSTART=%p curstart=%p.\n",
heapcreep, heapstart, curstart);
exit(-2);
}
else if(heapcreep && newstart+heapcreep != heapstart) {
cfprintf("Heap was not set properly: desired=%p result=%p zone=%lu.\n",
heapstart, newstart, heapcreep);
exit(-3);
}
}
int
PORTSTAT(void *path, CFSTAT *sbuf)
{
struct stat _stat;
int result = stat(path, &_stat);
if(result == 0)
fix_statbuf(&_stat, sbuf);
return result;
}
void
PORTFSTAT(int handle, CFSTAT *sbuf)
{
struct stat stat;
fstat(handle, &stat);
fix_statbuf(&stat, sbuf);
}
long
PORTREAD(long handle, void *mem_addr, STOR dsk_addr, long amount)
{
lseek(handle, dsk_addr.a0, SEEK_SET);
return read(handle, mem_addr, amount);
}
long
PORTWRITE(long handle, void *mem_addr, STOR dsk_addr, long amount)
{
lseek(handle, dsk_addr.a0, SEEK_SET);
return write(handle, mem_addr, amount);
}
void
PORTSEEK(long handle, STOR spot, int mode, STOR *loc)
{
STOR ret;
switch(mode)
{
case S_END:
mode = SEEK_END;
break;
case S_CUR:
mode = SEEK_CUR;
break;
case S_SET:
mode = SEEK_SET;
break;
default:
mode = -1;
}
ret.a4.s1 = 0;
ret.a4.s0 = lseek((int)handle, spot.a0, mode);
if(loc)
*loc = ret;
}
long
PORTOPEN(void *path, int mode)
{
int omode = O_BINARY;
if((mode & F_RDWR) == F_RDONLY)
omode |= O_RDONLY;
else if((mode & F_RDWR) == F_WRONLY)
omode |= O_WRONLY;
else if((mode & F_RDWR) == F_RDWR)
omode |= O_RDWR;
if(mode & F_TRUNC)
omode |= O_TRUNC;
if(mode & F_EXCL)
omode |= O_EXCL;
if(mode & F_APPEND)
omode |= O_APPEND;
return open(path,omode);
}
long
PORTCLOSE(long handle)
{
return close((int)handle);
}
long
PORTCREATE(void *path, int mode)
{
return creat(path, S_IREAD|S_IWRITE);
}
long
PORTUNLINK(void *path)
{
return unlink(path);
}
#if PCDOS == 1
static void
dos_truncate(short handle, long amount)
{
#include <dos.h>
union REGS r;
r.h.al = 0; /* SEEK_SET */
r.h.ah = 0x42; /* seek */
r.x.bx = handle;
r.x.dx = (short)amount;
r.x.cx = (short)(amount>>16);
intdos(&r,&r);
r.h.ah = 0x40; /* write */
r.x.bx = handle;
r.x.cx = 0; /* amount == 0 */
intdos(&r,&r);
r.h.ah = 0x3e; /* close */
r.x.bx = handle;
intdos(&r,&r);
}
#endif
long
PORTTRUNCATE(long handle, char *path, STOR amount)
{
#if PCDOS == 1
/* DJCC has a bugged ftruncate */
dos_truncate((short)handle, amount.a0);
return PORTOPEN(path, F_RDWR);
#else
ftruncate((int)handle, amount.a0);
return handle;
#endif
}
void
PORTCLOSETRUNC(long handle, STOR amount)
{
#if PCDOS == 1
/* DJCC has a bugged ftruncate */
dos_truncate((short)handle, amount.a0);
#else
ftruncate((int)handle, amount.a0);
close((int)handle);
#endif
}
void
PORTFLUSH(long handle)
{
#if 0
if(handle < 0)
sync();
else
#endif
fsync((int)handle);
}
char *
PORTGETCWD(void *buf, int maxlen)
{
char *result;
result = getcwd((char *)buf, maxlen);
((char *)buf)[maxlen] = 0;
if(result)
{
while(*((char *)buf))
{
if(*((char *)buf) == '\\') *((char *)buf) = '/';
++((char *)buf);
}
}
return result;
}
long
PORTCHDIR(void *path)
{
return chdir(path);
}
unsigned long
PORTTIME(void)
{
return time(NULL);
}
unsigned long
PORTCLOCK(void)
{
return clock();
}
volatile void
PORTABORT(void)
{
extern volatile void abort();
abort();
}
/* THE BASIC OS DRIVERS */
/* Primary Memory driver */
long
pmem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
{
switch(func)
{
case S_GETSPACE:
{
unsigned long min, nib, current;
amount = round_up(amount, CHUNK_SIZE);
min = round_up(amount / 4, CHUNK_SIZE);
nib = round_up(amount / 16, CHUNK_SIZE);
current = amount;
((STOR *)mem_addr)->a2.size = 0;
((STOR *)mem_addr)->a2.type = STO_CHUNK;
while(current >= min) {
if((((STOR *)mem_addr)->a1 = PORTSBRK(current)) != (void *)-1) {
if(((STOR *)mem_addr)->a0 & (NIBBLE-1))
{/* Normally the system uses NIBBLE bytes as the alignment */
((STOR *)mem_addr)->a0 =
round_up(((STOR *)mem_addr)->a0, NIBBLE);
current -= NIBBLE;
}
((STOR *)mem_addr)->a2.size = current;
return 0;
}
current -= nib;
}
return 1;
}
case S_GIVESPACE:
return 1;
default:
return 1;
}
return 0;
}
/* Secondary Memory driver */
long
smem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
{
if(!(testflags & 1))
{/*
IF SECONDARY MEMORY REALLY EXISTS, THEN PUT A REAL DRIVER HERE.
The system adapts to a 0 return from S_GETSPACE by mapping
secondary memory to primary memory when cfinit is called.
S_OPEN is never called.
*/
switch (func)
{
case S_GETSPACE:
*((long *)mem_addr) = 0;
break;
}
return -1;
} /* END: Real driver */
else {
/* THIS CODE IS JUST FOR TESTING PURPOSES, IT USES A LOCAL MEMORY BUFFER */
#define SMEMMAX (4096*1024)
static char *sbuf = NULL;
static long smemalloc = 0;
if(sbuf == NULL)
if((sbuf = PORTSBRK(SMEMMAX)) == (void *)-1)
return -1;
switch(func)
{
case S_CLOSE:
return 0; /* a real driver would do something */
case S_READBLK:
case S_WRITEBLK:
{
char *smemaddr = sbuf + dsk_addr.a0;
long xfer = amount;
if(dsk_addr.a0 + amount > smemalloc)
xfer = smemalloc - dsk_addr.a0;
if(xfer < 0) {
return -1;
}
if(func == S_READBLK)
mymemmove(mem_addr, smemaddr, xfer);
else mymemmove(smemaddr, mem_addr, xfer);
return xfer;
}
case S_GETSPACE:
amount = round_up(amount, CHUNK_SIZE);
((STOR *)mem_addr)->a0 = smemalloc;
((STOR *)mem_addr)->a2.size = 0;
((STOR *)mem_addr)->a2.type = STO_CHUNK;
if(amount + smemalloc < SMEMMAX) {
((STOR *)mem_addr)->a2.size = amount;
smemalloc += amount;
return 0;
} else {/* Not enough space available, return error + avail */
((STOR *)mem_addr)->a2.size =
(SMEMMAX - smemalloc) & ~CHUNK_SIZE;
return 1;
}
case S_GIVESPACE:
#if 0
cfprintf("SMEM: GIVESPACE at loc=%lx size=%lu curbase=%lx\n",
((STOR *)mem_addr)->a0, ((STOR *)mem_addr)->a2.size, smemalloc);
#endif
if(((STOR *)mem_addr)->a0 ==
smemalloc - ((STOR *)mem_addr)->a2.size)
{/* Accept returns if they are at the end */
smemalloc -= ((STOR *)mem_addr)->a2.size;
#if 0
cfprintf("SMEM: Truncate to %lu bytes\n", smemalloc);
#endif
return 0;
}
break;
default:
break;
}
return 1;
}/* END: test driver */
}
/* Internal file driver */
long
cfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
{
long result = 0;
switch(func)
{
case S_READBLK:
result = PORTREAD(handle, mem_addr, dsk_addr, amount);
break;
case S_WRITEBLK:
result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
break;
case S_GETSPACE:
{
u_long result;
STOR base;
STOR end;
PORTSEEK(handle, BIGZERO, S_END, &base);
amount = round_up(amount, CHUNK_SIZE);
end.a4.s0 = base.a0 + amount-1;
end.a4.s1 = 0;
PORTWRITE(handle, "0", end, 1);
PORTSEEK(handle, BIGZERO, S_END, &end);
result = end.a0 - base.a0;
((STOR *)mem_addr)->a0 = base.a0;
((STOR *)mem_addr)->a2.size = result;
((STOR *)mem_addr)->a2.type = STO_CHUNK;
return (result == amount) ? 0:1;
}
case S_GIVESPACE:
{
STOR base;
PORTSEEK(handle, BIGZERO, S_END, &base);
if((((STOR *)mem_addr)->a0 + ((STOR *)mem_addr)->a2.size) == base.a0)
{/* OK to return space if at end */
#if 0
long result;
base.a0 -= ((STOR *)mem_addr)->a2.size;
result = PORTTRUNCATE(handle, base);
#endif
return 0;
}
else return 1;
}
case S_OPEN:
result = PORTOPEN(mem_addr, handle);
break;
case S_CLOSE:
result = PORTCLOSE(handle);
break;
case S_CREATE:
result = PORTCREATE(mem_addr, handle);
break;
case S_UNLINK:
result = PORTUNLINK(mem_addr);
break;
case S_SEEK:
PORTSEEK(handle, dsk_addr, amount, mem_addr);
break;
case S_FLUSH:
PORTFLUSH(handle);
break;
case S_CLOSETRUNC: /* truncate and close, (PCDOS needs this) */
PORTCLOSETRUNC(handle, dsk_addr);
break;
default:
return 1;
}
return result;
}
/* External file driver */
long
xfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
{
long result = 0;
switch(func)
{
case S_GETSPACE:
((STOR *)mem_addr)->a2.size = 0;
case S_GIVESPACE:
return 1;
case S_OPEN:
result = PORTOPEN(mem_addr, handle);
break;
case S_CLOSE:
result = PORTCLOSE(handle);
break;
case S_UNLINK:
result = PORTUNLINK(mem_addr);
break;
case S_CREATE:
result = PORTCREATE(mem_addr,handle);
break;
case S_READBLK:
result = PORTREAD(handle, mem_addr, dsk_addr, amount);
break;
case S_WRITEBLK:
result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
break;
case S_SEEK:
PORTSEEK(handle, dsk_addr, amount, mem_addr);
break;
case S_FLUSH:
PORTFLUSH(handle);
break;
default:
return 1;
}
return result;
}
void *
PORTOPENDIR(char *name)
{
return opendir(name);
}
void *
PORTREADDIR(void *it, CFDIRENT *d)
{
struct dirent *rd;
if((rd = readdir(it))) {
d->d_namlen = rd->d_namlen;
d->d_name = rd->d_name;
d->d_mode = M_EXTRNFILE;
}
return rd;
}
void
PORTTELLDIR(void *it, STOR *loc)
{
STOR me;
me.item = 0;
me.a0 = telldir(it);
if(loc)
*loc = me;
}
void
PORTSEEKDIR(void *it, STOR *loc)
{
seekdir(it, loc->a0);
}
void
PORTREWINDDIR(void *it)
{
rewinddir(it);
}
long
PORTCLOSEDIR(void *it)
{
return closedir(it);
}
int
PORTPRINT(int c)
{
return write(1, &c, 1);
}
#if 0
/*
THIS CODE IS FOR SAMPLE PURPOSES ONLY -- THE REAL CODE IS IN THE LIBRARY
PROGRAMMERS WHO WISH TO CREATE CUSTOM COMPARISON ROUTINES CAN USE THESE
FUNCTIONS AS MODELS.
*/
/*
default_keycmp - system key comparison
Return: LESS if keya < keyb
EQUAL if keya == keyb
GREATER if keya > keyb
*/
static __inline__ int
mymemcmp(unsigned char *a, unsigned char *b, int len)
{
int result = 0;
do {
if((result = ((int)*a++) - ((int)*b++)))
return result;
} while(--len);
return result;
}
int
default_keycmp (void *keya, int lena, void *keyb, int lenb)
{
int result;
if (lena == 0)
return ( (lenb == 0) ? EQUAL : LESS );
else if (lenb == 0)
return (GREATER);
result = mymemcmp (keya, keyb, ((lena<lenb)?lena:lenb));
if (result < 0)
return LESS;
if (result > 0)
return GREATER;
return ((lena == lenb) ? EQUAL : ((lena < lenb) ? LESS : GREATER));
}
/*
default_itemcmp - system item comparison
Return: LESS-1 if itema < itemb
EQUAL+1 if itema == itemb
GREATER+1 if itema > itemb
*/
int
default_itemcmp (Item *a, Item *b)
{
return ( (a->item == b->item) ?
EQUAL+1 : ((a->item < b->item) ? LESS-1 : GREATER+1) );
}
#endif